package com.itaming.lycheeframework.security.token.provider;

import com.itaming.lycheeframework.security.exception.AccessDeniedException;
import com.itaming.lycheeframework.security.properties.LycheeSecurityProperties;
import com.itaming.lycheeframework.security.result.SecurityErrorCode;
import com.itaming.lycheeframework.security.token.TokenExpiresInPair;
import com.itaming.lycheeframework.support.utils.LambdaUtil;
import com.itaming.lycheeframework.support.utils.StringPool;
import com.itaming.lycheeframework.support.utils.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 默认 Token 过期时间提供者
 *
 * @author A.Ming
 */
@Slf4j
@RequiredArgsConstructor
public class DefaultTokenExpiresInProvider implements TokenExpiresInProvider {

    /**
     * Token 配置参数
     */
    private final LycheeSecurityProperties.Token tokenProperties;

    /**
     * 获取客户端 Token 过期时间
     *
     * @param clientId 客户端标识符
     * @return 过期时间
     */
    @Override
    public TokenExpiresInPair get(String clientId) {
        Map<String, TokenExpiresInPair> clientExpiresIn = tokenProperties.getExpiresIn();
        if (!clientExpiresIn.containsKey(clientId)) {
            log.warn(buildLogMessage(clientId));
            throw new AccessDeniedException(SecurityErrorCode.INVALID_CLIENT_ID);
        }

        return clientExpiresIn.get(clientId);
    }

    /**
     * 构建日志消息
     *
     * @param clientId 客户端标识符
     * @return 日志消息
     */
    private String buildLogMessage(String clientId) {
        String tokenPropsName = StringUtil.camelToKebab(LambdaUtil.getPropertyName(LycheeSecurityProperties::getToken));
        String expiresInPropsName = StringUtil.camelToKebab(LambdaUtil.getPropertyName(LycheeSecurityProperties.Token::getExpiresIn));
        String propsKey = String.join(StringPool.DOT, LycheeSecurityProperties.PREFIX, tokenPropsName, expiresInPropsName);
        return "Invalid clientId '%s', please configure token expiration under properties key '%s'".formatted(clientId, propsKey);
    }

}
